﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ADIGRE.Infrastructure.Queries.Authentication;
using SharpArch.NHibernate.Contracts.Repositories;
using ADIGRE.Domain;
using ADIGRE.MVC3.Web.Util;
using ADIGRE.MVC3.Web.Controllers.ViewModels;
using ADIGRE.Infrastructure.Queries.Pessoa;
using SharpArch.NHibernate.Web.Mvc;
using ADIGRE.Infrastructure.Queries.Despesa;
using ADIGRE.Domain.RoutineTable;

namespace ADIGRE.MVC3.Web.Controllers
{
    public class SaidaController : ControllerAuthorize
    {

        private readonly IAuthenticationService _authenticationService;
        private readonly IDespesaQuery _DespesaQuery;
        private readonly IPessoaQuery _PessoaQueryRepository;
        private readonly INHibernateRepository<Recibo> _ReciboRepository;
        private readonly INHibernateRepository<Despesa> _DespesaRepository;
        private readonly INHibernateRepository<Saida> _SaidaRepository;
        private readonly INHibernateRepository<Lancamento> _LancamentoRepository;
        private readonly INHibernateRepository<Pagamento> _PagamentoRepository;
        private readonly INHibernateRepository<BalancoMensal> _BalancoMensal;

        public SaidaController(IAuthenticationService authenticationService, IPessoaQuery PessoaQueryRepository,
            INHibernateRepository<Lancamento> LancamentoRepository, INHibernateRepository<BalancoMensal> BalancoMensal,
            INHibernateRepository<Despesa> DespesaRepository, IDespesaQuery DespesaQuery, INHibernateRepository<Recibo> ReciboRepository,
            INHibernateRepository<Pagamento> PagamentoRepository, INHibernateRepository<Saida> SaidaRepository)
        {
            this._authenticationService = authenticationService;
            this._ReciboRepository = ReciboRepository;
            this._DespesaRepository = DespesaRepository;
            this._LancamentoRepository = LancamentoRepository;
            this._SaidaRepository = SaidaRepository;
            this._PagamentoRepository = PagamentoRepository;
            this._PessoaQueryRepository = PessoaQueryRepository;
            this._DespesaQuery = DespesaQuery;
            this._BalancoMensal = BalancoMensal;
        }

        //
        // GET: /Saida/

        [Transaction]
        public ActionResult Delete(int Id)
        {
            //try
            //{
            //    var user = _authenticationService.GetUserAuthenticated();

            //    var saida = _SaidaRepository.Get(Id);
            //    saida.ValidarExclusao(user);
            //    _SaidaRepository.Update(saida);

            //    if (!(saida.EnumLancamento.Equals(EnumLancamento.Recibo) && saida.Despesa.EnumLancamento.Equals(EnumLancamento.Pagamento)))
            //        saida.Despesa.NuParcelasQuitadas--;
            //    saida.Despesa.VlQuitado -= saida.VlLancamento;
            //    saida.Despesa.IsEncerrado = false;
            //    saida.Despesa.Validar(user);
            //    _DespesaRepository.Update(saida.Despesa);

            //    _Feedback = GlobalResources.Sistema.Feedback.SUCCESS_DELETE;
            //    switch (saida.EnumLancamento)
            //    {
            //        case EnumLancamento.Pagamento:
            //            return RedirectToAction("ListPagamento");
            //        case EnumLancamento.Recibo:
            //            return RedirectToAction("ListRecibo");
            //    }
            //}
            //catch (Exception ex)
            //{
            //    _ObjLog.Error("SaidaController(Delete): " + ex.ToString());
            //    _Feedback = GlobalResources.Sistema.Feedback.ERROR_SYSTEM;
            //}
            return RedirectToAction("Index", "Home");
        }

        public ActionResult GerarRecibo()
        {
            try
            {
                var user = _authenticationService.GetUserAuthenticated();
                if (user.Pessoa != null)
                    ViewBag.UsuarioLogado = user.Pessoa.NmPessoa;
                else
                    ViewBag.UsuarioLogado = user.NmLogin;
                ViewBag.IsRoot = user.IsRoot;
                ViewBag.EnumPerfilAcesso = user.EnumPerfilAcesso;
                if (!(user.EnumPerfilAcesso.Equals(EnumPerfilAcesso.Tesoureiro)))
                    return RedirectToAction("Index", "Home");

                var vmRecibo = new ReciboViewModel();
                var dtRetroativa = _BalancoMensal.GetAll().Max(x => x.DtPeriodo);
                if (dtRetroativa.HasValue)
                    vmRecibo.DtRetroativa = dtRetroativa.Value.AddMonths(1).AddDays(-1);

                var combo = new ComboListItem();
                List<Pessoa> pessoas = _PessoaQueryRepository.GelAllPessoa().Where(x => x.NmPessoa != _Anonimo).ToList();
                List<Despesa> despesas = _DespesaQuery.GetReciboEmAberto().ToList();
                ViewBag.Favorecido = combo.ComboPessoas(pessoas);
                ViewBag.Despesa = combo.ComboDespesas(despesas);
                return View(vmRecibo);
            }
            catch (Exception ex)
            {
                _ObjLog.Error("SaidaController(GerarRecibo): " + ex.ToString());
                _Feedback = GlobalResources.Sistema.Feedback.ERROR_SYSTEM;
            }
            return RedirectToAction("Index", "Home");
        }

        [HttpPost, Transaction]
        public ActionResult GerarRecibo(FormCollection collection)
        {
            ReciboViewModel vmRecibo = new ReciboViewModel();

            try
            {
                var user = _authenticationService.GetUserAuthenticated();
                if (user.Pessoa != null)
                    ViewBag.UsuarioLogado = user.Pessoa.NmPessoa;
                else
                    ViewBag.UsuarioLogado = user.NmLogin;
                ViewBag.IsRoot = user.IsRoot;
                ViewBag.EnumPerfilAcesso = user.EnumPerfilAcesso;
                if (!(user.EnumPerfilAcesso.Equals(EnumPerfilAcesso.Tesoureiro)))
                    return RedirectToAction("Index", "Home");

                TryUpdateModel(vmRecibo, collection);
                bool invalid = false;

                if (vmRecibo.Recibo.Despesa.Id == 0 && string.IsNullOrWhiteSpace(vmRecibo.NovaDespesa.NmDespesa))
                {
                    invalid = true;
                    ModelState.AddModelError("", GlobalResources.Sistema.Feedback.ERROR_EMPTY_DESPESA);
                }

                if (!vmRecibo.Recibo.DtLancamento.HasValue)
                {
                    invalid = true;
                    ModelState.AddModelError("", GlobalResources.Sistema.Feedback.ERROR_RECIBO_DATA);
                }
                else if (vmRecibo.DtRetroativa.HasValue && vmRecibo.DtRetroativa.Value.Date == vmRecibo.Recibo.DtLancamento.Value.Date)
                {
                    invalid = true;
                    ModelState.AddModelError("", GlobalResources.Sistema.Feedback.WARNING_DATA_RETROATIVA);
                }

                if (vmRecibo.Recibo.VlLancamento <= 0)
                {
                    invalid = true;
                    ModelState.AddModelError("", GlobalResources.Sistema.Feedback.ERROR_RECIBO_VALOR);
                }
                if (vmRecibo.Recibo.Favorecido.Id == 0)
                {
                    invalid = true;
                    ModelState.AddModelError("", GlobalResources.Sistema.Feedback.ERROR_RECIBO_FAVORECIDO);
                }
                if (vmRecibo.Recibo.Despesa.Id == 0 && !string.IsNullOrWhiteSpace(vmRecibo.NovaDespesa.NmDespesa))
                {
                    if (_DespesaQuery.GetAll().Where(x => x.NmDespesa.Trim().Equals(vmRecibo.NovaDespesa.NmDespesa.Trim())).Count() > 0)
                    {
                        invalid = true;
                        ModelState.AddModelError("", GlobalResources.Sistema.Feedback.WARNING_DESPESA_EXISTS);
                    }
                }

                if (invalid)
                {
                    List<Pessoa> pessoas = _PessoaQueryRepository.GelAllPessoa().Where(x => x.NmPessoa != _Anonimo).ToList();
                    List<Despesa> despesas = _DespesaQuery.GetReciboEmAberto().ToList();
                    ViewBag.Favorecido = new ComboListItem().ComboPessoas(pessoas);
                    ViewBag.Despesa = new ComboListItem().ComboDespesas(despesas);
                    return View(vmRecibo);
                }


                if (vmRecibo.Recibo.Despesa.Id == 0 && !string.IsNullOrWhiteSpace(vmRecibo.NovaDespesa.NmDespesa))
                {
                    vmRecibo.NovaDespesa.Validar(user);
                    vmRecibo.NovaDespesa.EnumLancamento = EnumLancamento.Recibo;
                    vmRecibo.NovaDespesa.EnumModalidadePagamento = EnumModalidadePagamento.ParcelaContinuada;
                    vmRecibo.Recibo.Despesa = vmRecibo.NovaDespesa;
                }
                else
                {
                    vmRecibo.Recibo.Despesa.Validar(user);
                    var d = _DespesaRepository.Get(vmRecibo.Recibo.Despesa.Id);
                    d.Complete(vmRecibo.Recibo.Despesa);
                    vmRecibo.Recibo.Despesa = d;
                }

                vmRecibo.Recibo.Despesa.VlQuitado += vmRecibo.Recibo.VlLancamento;
                if (vmRecibo.Recibo.Despesa.EnumLancamento.Equals(EnumLancamento.Recibo))
                    vmRecibo.Recibo.Despesa.NuParcelasQuitadas++;
                else if ((vmRecibo.Recibo.Despesa.EnumModalidadePagamento != EnumModalidadePagamento.ParcelaContinuada) && vmRecibo.Recibo.Despesa.VlQuitado >= vmRecibo.Recibo.Despesa.VlTotal)
                    vmRecibo.Recibo.Despesa.IsEncerrado = true;
                _DespesaRepository.SaveOrUpdate(vmRecibo.Recibo.Despesa);

                vmRecibo.Recibo.Validar(user);
                if (vmRecibo.Recibo.Id > 0)
                {
                    var r = _ReciboRepository.Get(vmRecibo.Recibo.Id);
                    r.Complete(vmRecibo.Recibo);
                    vmRecibo.Recibo = r;
                }
                _ReciboRepository.SaveOrUpdate(vmRecibo.Recibo);
                _Feedback = GlobalResources.Sistema.Feedback.SUCCESS_CADASTRO;
                return RedirectToAction("ListRecibo", new { Id = vmRecibo.Recibo.Id });

            }
            catch (Exception ex)
            {
                _ObjLog.Error("SaidaController(GerarRecibo[]): " + ex.ToString());
                ModelState.AddModelError("", GlobalResources.Sistema.Feedback.ERROR_INVALID_DATA);

            }
            return View(vmRecibo);
        }

        public ActionResult EmitirRecibo(int Id)
        {
            try
            {
                var user = _authenticationService.GetUserAuthenticated();
                if (user.EnumPerfilAcesso.Equals(EnumPerfilAcesso.Tesoureiro))
                {
                    var recibo = _ReciboRepository.Get(Id);
                    if (recibo != null)
                        return View(recibo);
                    _Feedback = GlobalResources.Sistema.Feedback.ERROR_RECIBO_NOT_FOUND;
                }
            }
            catch (Exception ex)
            {
                _ObjLog.Error("SaidaController(EmitirRecibo): " + ex.ToString());
                _Feedback = GlobalResources.Sistema.Feedback.ERROR_SYSTEM;
            }
            return RedirectToAction("Index", "Home");
        }

        public ActionResult ListRecibo(int Id = 0)
        {
            try
            {
                var user = _authenticationService.GetUserAuthenticated();
                if (user.Pessoa != null)
                    ViewBag.UsuarioLogado = user.Pessoa.NmPessoa;
                else
                    ViewBag.UsuarioLogado = user.NmLogin;
                ViewBag.EnumPerfilAcesso = user.EnumPerfilAcesso;
                ViewBag.Id = (!user.EnumPerfilAcesso.Equals(EnumPerfilAcesso.Tesoureiro)) ? 0 : Id;
                List<Recibo> recibos = _ReciboRepository.GetAll().Where(x => !x.IsExcluido).OrderByDescending(x => x.DtLancamento).ToList();
                if (recibos.Count == 0)
                    _Feedback = GlobalResources.Sistema.Feedback.ERROR_RECIBO_NOT_FOUND;
                return View(recibos);
            }
            catch (Exception ex)
            {
                _ObjLog.Error("SaidaController(ListRecibo): " + ex.ToString());
                _Feedback = GlobalResources.Sistema.Feedback.ERROR_SYSTEM;
            }
            return RedirectToAction("Index", "Home");
        }

        public ActionResult ListPagamento()
        {
            try
            {
                var user = _authenticationService.GetUserAuthenticated();
                if (user.Pessoa != null)
                    ViewBag.UsuarioLogado = user.Pessoa.NmPessoa;
                else
                    ViewBag.UsuarioLogado = user.NmLogin;
                ViewBag.EnumPerfilAcesso = user.EnumPerfilAcesso;

                List<Pagamento> pagamento = _PagamentoRepository.GetAll().Where(x => !x.IsExcluido).OrderByDescending(x => x.DtLancamento).ToList();
                if (pagamento.Count == 0)
                    _Feedback = GlobalResources.Sistema.Feedback.ERROR_RECIBO_NOT_FOUND;
                return View(pagamento);
            }
            catch (Exception ex)
            {
                _ObjLog.Error("SaidaController(ListRecibo): " + ex.ToString());
                _Feedback = GlobalResources.Sistema.Feedback.ERROR_SYSTEM;
            }
            return RedirectToAction("Index", "Home");
        }

        public ActionResult PagamentoConta(int Id = 0)
        {
            PagamentoViewModel vmPagamento = new PagamentoViewModel();
            try
            {
                var user = _authenticationService.GetUserAuthenticated();
                if (user.Pessoa != null)
                    ViewBag.UsuarioLogado = user.Pessoa.NmPessoa;
                else
                    ViewBag.UsuarioLogado = user.NmLogin;
                ViewBag.EnumPerfilAcesso = user.EnumPerfilAcesso;
                if (!(user.EnumPerfilAcesso.Equals(EnumPerfilAcesso.Tesoureiro)))
                    return RedirectToAction("Index", "Home");

                var dtRetroativa = _BalancoMensal.GetAll().Max(x => x.DtPeriodo);
                if (dtRetroativa.HasValue)
                    vmPagamento.DtRetroativa = dtRetroativa.Value.AddMonths(1).AddDays(-1);

                if (Id > 0)
                {
                    var pagamento = _PagamentoRepository.Get(Id);
                    if (!pagamento.IsExcluido)
                        vmPagamento.Pagamento = pagamento;
                }
                ViewBag.Despesa = new ComboListItem().ComboDespesas(_DespesaQuery.GetPagamentoEmAberto().ToList());
                ViewBag.EnumModalidadePagamento = new ComboListItem().ComboModalidadePagamento();
            }
            catch (Exception ex)
            {
                _ObjLog.Error("SaidaController(PagamentoConta): " + ex.ToString());
                ModelState.AddModelError("", GlobalResources.Sistema.Feedback.ERROR_SYSTEM);

            }
            return View(vmPagamento);
        }

        [HttpPost, Transaction]
        public ActionResult PagamentoConta(FormCollection collection)
        {
            PagamentoViewModel vmPagamento = new PagamentoViewModel();
            try
            {
                var user = _authenticationService.GetUserAuthenticated();
                if (user.Pessoa != null)
                    ViewBag.UsuarioLogado = user.Pessoa.NmPessoa;
                else
                    ViewBag.UsuarioLogado = user.NmLogin;
                ViewBag.EnumPerfilAcesso = user.EnumPerfilAcesso;
                if (!(user.EnumPerfilAcesso.Equals(EnumPerfilAcesso.Tesoureiro)))
                    return RedirectToAction("Index", "Home");

                TryUpdateModel(vmPagamento, collection);
                bool isValid = true;
                if (vmPagamento.Pagamento.Despesa.Id == 0)
                {
                    if (string.IsNullOrWhiteSpace(vmPagamento.NovaDespesa.NmDespesa))
                    {
                        ModelState.AddModelError("", GlobalResources.Sistema.Feedback.ERROR_EMPTY_DESPESA);
                        isValid = false;
                    }
                    else if (_DespesaQuery.GetPagamentoEmAberto().Where(x => x.NmDespesa.Equals(vmPagamento.NovaDespesa.NmDespesa.Trim())).Count() > 0)
                    {
                        ModelState.AddModelError("", GlobalResources.Sistema.Feedback.WARNING_DESPESA_EXISTS);
                        isValid = false;
                    }

                    switch (vmPagamento.NovaDespesa.EnumModalidadePagamento)
                    {
                        case EnumModalidadePagamento.NA:
                            ModelState.AddModelError("", GlobalResources.Sistema.Feedback.ERROR_MODALIDADE_PAGAMENTO_EMPTY);
                            isValid = false;
                            break;
                        case EnumModalidadePagamento.ParcelaFixa:
                            if (vmPagamento.NovaDespesa.NuParcelas <= 0)
                            {
                                ModelState.AddModelError("", GlobalResources.Sistema.Feedback.ERROR_QTD_PARCELAS);
                                isValid = false;
                            }
                            if (vmPagamento.NovaDespesa.VlParcela <= 0)
                            {
                                ModelState.AddModelError("", GlobalResources.Sistema.Feedback.ERROR_VL_PARCELAS);
                                isValid = false;
                            }
                            break;
                        case EnumModalidadePagamento.ParcelaUnica:
                            if (vmPagamento.NovaDespesa.VlTotal <= 0)
                            {
                                ModelState.AddModelError("", GlobalResources.Sistema.Feedback.ERROR_VL_TOTAL);
                                isValid = false;
                            }
                            break;
                        case EnumModalidadePagamento.ParcelaVariavel:
                            if (vmPagamento.NovaDespesa.VlTotal <= 0)
                            {
                                ModelState.AddModelError("", GlobalResources.Sistema.Feedback.ERROR_VL_TOTAL);
                                isValid = false;
                            }
                            break;
                        default:
                            break;
                    }
                }

                if (vmPagamento.Pagamento.VlLancamento <= 0)
                {
                    ModelState.AddModelError("", GlobalResources.Sistema.Feedback.ERROR_EMPTY_VALOR);
                    isValid = false;
                }
                else if (vmPagamento.DtRetroativa.HasValue && vmPagamento.DtRetroativa.Value.Date == vmPagamento.Pagamento.DtLancamento.Value.Date)
                {
                    isValid = false;
                    ModelState.AddModelError("", GlobalResources.Sistema.Feedback.WARNING_DATA_RETROATIVA);
                }
                if (!vmPagamento.Pagamento.DtLancamento.HasValue)
                {
                    ModelState.AddModelError("", GlobalResources.Sistema.Feedback.ERROR_EMPTY_DATA);
                    isValid = false;
                }

                if (isValid)
                {
                    if (vmPagamento.Pagamento.Despesa.Id == 0)
                    {
                        vmPagamento.NovaDespesa.EnumLancamento = EnumLancamento.Pagamento;
                        vmPagamento.Pagamento.Despesa = vmPagamento.NovaDespesa;
                    }
                    vmPagamento.Pagamento.Despesa.Validar(user);

                    if (vmPagamento.Pagamento.Despesa.Id > 0)
                    {
                        var d = _DespesaRepository.Get(vmPagamento.Pagamento.Despesa.Id);
                        d.Complete(vmPagamento.Pagamento.Despesa);
                        vmPagamento.Pagamento.Despesa = d;
                    }

                    vmPagamento.Pagamento.Despesa.VlQuitado += vmPagamento.Pagamento.VlLancamento;
                    vmPagamento.Pagamento.Despesa.NuParcelasQuitadas++;
                    switch (vmPagamento.Pagamento.Despesa.EnumModalidadePagamento)
                    {
                        case EnumModalidadePagamento.ParcelaFixa:
                            if (vmPagamento.Pagamento.Despesa.NuParcelas == vmPagamento.Pagamento.Despesa.NuParcelasQuitadas
                                && vmPagamento.Pagamento.Despesa.VlTotal == vmPagamento.Pagamento.Despesa.VlQuitado)
                                vmPagamento.Pagamento.Despesa.IsEncerrado = true;
                            break;
                        case EnumModalidadePagamento.ParcelaUnica:
                            vmPagamento.Pagamento.Despesa.IsEncerrado = true;
                            break;
                        default:
                            break;
                    }

                    _DespesaRepository.SaveOrUpdate(vmPagamento.Pagamento.Despesa);

                    vmPagamento.Pagamento.Validar(user);
                    if (vmPagamento.Pagamento.Id > 0)
                    {
                        var p = _PagamentoRepository.Get(vmPagamento.Pagamento.Id);
                        p.Complete(vmPagamento.Pagamento);
                        vmPagamento.Pagamento = p;
                    }

                    _PagamentoRepository.SaveOrUpdate(vmPagamento.Pagamento);

                    //if (vmPagamento.Pagamento.Despesa.Saidas.Where(x => x.Id == vmPagamento.Pagamento.Id).Count() == 0)
                    //{
                    //    vmPagamento.Pagamento.Despesa.Saidas.Add(vmPagamento.Pagamento);
                    //    _DespesaRepository.Update(vmPagamento.Pagamento.Despesa);
                    //}
                    _Feedback = GlobalResources.Sistema.Feedback.SUCCESS_CADASTRO;
                    return RedirectToAction("ListPagamento");
                }
            }
            catch (Exception ex)
            {
                _ObjLog.Error("SaidaController(PagamentoConta[]): " + ex.ToString());
                ModelState.AddModelError("", GlobalResources.Sistema.Feedback.ERROR_INVALID_DATA);
            }
            ViewBag.Despesa = new ComboListItem().ComboDespesas(_DespesaQuery.GetPagamentoEmAberto().ToList());
            ViewBag.EnumModalidadePagamento = new ComboListItem().ComboModalidadePagamento();
            return View(vmPagamento);
        }

        public ActionResult LoadPagamento()
        {
            var vmPagamento = new PagamentoViewModel();
            try
            {
                var user = _authenticationService.GetUserAuthenticated();
                ViewBag.EnumPerfilAcesso = user.EnumPerfilAcesso;
                if (!(user.EnumPerfilAcesso.Equals(EnumPerfilAcesso.Tesoureiro)))
                    return RedirectToAction("Index", "Home");

                var collection = new FormCollection(Request.QueryString);
                TryUpdateModel(vmPagamento, collection);
                var despesa = _DespesaRepository.Get(vmPagamento.Pagamento.Despesa.Id);
                switch (despesa.EnumModalidadePagamento)
                {
                    case EnumModalidadePagamento.ParcelaUnica:
                        vmPagamento.Pagamento.VlLancamento = despesa.VlTotal;
                        break;
                    case EnumModalidadePagamento.ParcelaFixa:
                        vmPagamento.Pagamento.VlLancamento = despesa.VlParcela;
                        despesa.NuParcelasQuitadas++;
                        break;
                    case EnumModalidadePagamento.ParcelaVariavel:
                        despesa.NuParcelasQuitadas++;
                        break;
                    default:
                        break;
                }
                vmPagamento.Pagamento.Despesa = despesa;
            }
            catch (Exception ex)
            {
                _ObjLog.Error("SaidaController(LoadPagamento): " + ex.ToString());
                ModelState.AddModelError("", GlobalResources.Sistema.Feedback.ERROR_SYSTEM);
            }
            return View("_PagamentoConta", vmPagamento);
        }
    }
}
